package thread.pool;

import java.util.concurrent.*;

public class CustomThreadPoolDemo {

    public static void main(String[] args) {
        // 演示不同的拒绝策略
        demonstrateRejectionPolicies();
    }

    public static void demonstrateRejectionPolicies() {
        System.out.println("=== 演示不同的拒绝策略 ===");

        // 1. AbortPolicy - 抛出异常（默认策略）
        demonstrateAbortPolicy();

        // 2. CallerRunsPolicy - 调用线程处理
        demonstrateCallerRunsPolicy();

        // 3. DiscardPolicy - 直接丢弃
        demonstrateDiscardPolicy();

        // 4. DiscardOldestPolicy - 丢弃队列中最老的任务
        demonstrateDiscardOldestPolicy();
    }

    /**
     * AbortPolicy - 抛出RejectedExecutionException异常
     */
    public static void demonstrateAbortPolicy() {
        System.out.println("\n--- AbortPolicy (抛出异常) ---");
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                1, 1, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1),
                new ThreadPoolExecutor.AbortPolicy()
        );

        submitTasksAndHandleRejection(pool, "AbortPolicy");

        shutdownAndAwaitTermination(pool);
    }

    /**
     * CallerRunsPolicy - 由调用线程执行任务
     */
    public static void demonstrateCallerRunsPolicy() {
        System.out.println("\n--- CallerRunsPolicy (调用线程运行) ---");
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                1, 1, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

        submitTasksAndHandleRejection(pool, "CallerRunsPolicy");

        shutdownAndAwaitTermination(pool);
    }

    /**
     * DiscardPolicy - 静默丢弃任务
     */
    public static void demonstrateDiscardPolicy() {
        System.out.println("\n--- DiscardPolicy (静默丢弃) ---");
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                1, 1, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1),
                new ThreadPoolExecutor.DiscardPolicy()
        );

        submitTasksAndHandleRejection(pool, "DiscardPolicy");

        shutdownAndAwaitTermination(pool);
    }

    /**
     * DiscardOldestPolicy - 丢弃队列中最老的任务
     */
    public static void demonstrateDiscardOldestPolicy() {
        System.out.println("\n--- DiscardOldestPolicy (丢弃最老任务) ---");
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                1, 1, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1),
                new ThreadPoolExecutor.DiscardOldestPolicy()
        );

        submitTasksAndHandleRejection(pool, "DiscardOldestPolicy");

        shutdownAndAwaitTermination(pool);
    }

    /**
     * 提交多个任务以触发拒绝策略
     */
    private static void submitTasksAndHandleRejection(ThreadPoolExecutor pool, String policyName) {
        try {
            // 提交超过队列容量的任务
            for (int i = 1; i <= 5; i++) {
                final int taskId = i;
                pool.submit(() -> {
                    System.out.println(policyName + ": Task " + taskId + " executed by " + Thread.currentThread().getName());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                });
            }
        } catch (RejectedExecutionException e) {
            System.out.println(policyName + ": Task被拒绝，异常信息: " + e.getMessage());
        }

        // 显示当前线程池状态
        System.out.println(policyName + ": 活动线程数=" + pool.getActiveCount() + 
                          ", 队列大小=" + pool.getQueue().size() + 
                          ", 完成任务数=" + pool.getCompletedTaskCount());
    }

    /**
     * 优雅关闭线程池
     */
    private static void shutdownAndAwaitTermination(ExecutorService pool) {
        try {
            pool.shutdown();
            if (!pool.awaitTermination(3, TimeUnit.SECONDS)) {
                System.out.println("线程池未在规定时间内完成，强制关闭");
                pool.shutdownNow();
            }
        } catch (InterruptedException e) {
            pool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}
